package com.kreedx.audio

import android.app.Service
import android.content.Context
import android.media.*
import android.os.Environment
import android.support.v4.graphics.TypefaceCompatUtil.closeQuietly
import android.util.Log
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.lang.Exception

class AutioHelper(context : Context) {

    var context = context

    var mIsPalying = false
    var mAudioFile: File? = null
    var mFileOutputStream:FileOutputStream? = null
    var mAudioRecorder:AudioRecord? = null
    var mIsRecording = false
    var mBuffer = ByteArray(2048)

    fun getManager():AutioManager {
        return object :AutioManager {
            override fun record() {
                mIsRecording = true
                try {
                    // 1、输出pcm文件
                    mAudioFile = File(
                        Environment.getExternalStorageDirectory().absolutePath + "/RecorderTest/" +
                            System.currentTimeMillis() + ".pcm")
                    mAudioFile?.run {
                        Log.e("path",parentFile.absolutePath)
                        parentFile.mkdirs()
                        createNewFile()
                    }
                    mFileOutputStream =  FileOutputStream(mAudioFile)

                    // 2、配置AudioRecord
                    // 声音来源
                    val audioSource = MediaRecorder.AudioSource.MIC
                    // 采样率 Hz
                    val sampleRate = 44100
                    // 音频通道的配置 MONO 单声道
                    val channelConfig = AudioFormat.CHANNEL_IN_MONO
                    // 返回音频数据的格式
                    val audioFormat = AudioFormat.ENCODING_PCM_16BIT
                    //AudioRecord能接受的最小的buffer大小
                    val minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat)
                    mAudioRecorder =  AudioRecord(audioSource, sampleRate, channelConfig,
                    audioFormat, Math.max(minBufferSize, 2048))

                    // 3、开始录音
                    mAudioRecorder?.run { startRecording() }


                    // 4、一边从AudioRecord中读取声音数据到初始化的buffer，一边将buffer中数据导入数据流，写入文件中
                    while (mIsRecording) { // 标志位，是否停止录音
                        val read = mAudioRecorder!!.read(mBuffer, 0, 2048)
                        if (read > 0) {
                            mFileOutputStream?.run { write(mBuffer, 0, read) }
                            // 也可以在这里对音频数据进行处理，压缩、直播等
                        }
                    }

                    Log.e("audio","stop")
                    // 5、停止录音，释放资源

                    mAudioRecorder?.run {
                        stop()
                        release()
                        null
                    }
                    mFileOutputStream?.run {
                        close()
                    }

                } catch ( e :IOException) {
                    e.printStackTrace()
                } finally {
                    if (mAudioRecorder != null) {
                        mAudioRecorder?.run {
                            release()
                            null
                        }
                    }
                }

            }

            override fun end() {
                mIsRecording = false
            }
            override fun play() {
                mIsPalying = true

                if(mAudioFile == null){
                    mAudioFile  = File(
                        Environment.getExternalStorageDirectory().absolutePath + "/RecorderTest/1.pcm")
                }
                // 音频流的类型
                // STREAM_ALARM：警告声
                // STREAM_MUSIC：音乐声
                // STREAM_RING：铃声
                // STREAM_SYSTEM：系统声音，例如低电提示音，锁屏音等
                // STREAM_VOCIE_CALL：通话声
                val streamType = AudioManager.STREAM_MUSIC

                // 采样率 Hz
                val sampleRate = 44100
                // 单声道
                val channelConfig = AudioFormat.CHANNEL_OUT_MONO

                // 音频数据表示的格式
                val audioFormat = AudioFormat.ENCODING_PCM_16BIT

                // MODE_STREAM：在这种模式下，通过write一次次把音频数据写到AudioTrack中。这和平时通过
                // write系统调用往文件中写数据类似，但这种工作方式每次都需要把数据从用户提供的Buffer中拷贝到
                // AudioTrack内部的Buffer中，这在一定程度上会使引入延时。为解决这一问题，AudioTrack就引入
                // 了第二种模式。

                // MODE_STATIC：这种模式下，在play之前只需要把所有数据通过一次write调用传递到AudioTrack
                // 中的内部缓冲区，后续就不必再传递数据了。这种模式适用于像铃声这种内存占用量较小，延时要求较
                // 高的文件。但它也有一个缺点，就是一次write的数据不能太多，否则系统无法分配足够的内存来存储
                // 全部数据。
                val mode = AudioTrack.MODE_STREAM

                val minBufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat)

                val audioTrack =  AudioTrack(streamType, sampleRate, channelConfig, audioFormat, Math.max(minBufferSize, 2048), mode)

                var mFileInputStream:FileInputStream? = null
                try {
                    mFileInputStream = FileInputStream(mAudioFile)
                    var read:Int
                    audioTrack.play()
                    read = mFileInputStream.read(mBuffer)
                    while (read > 0) {
                        val ret = audioTrack.write(mBuffer, 0, read)
                        when (ret) {
                            AudioTrack.ERROR_BAD_VALUE,AudioTrack.ERROR_INVALID_OPERATION
                                ,AudioManager.ERROR_DEAD_OBJECT
                            -> palyFaile()
                        }
                        read = mFileInputStream.read(mBuffer)
                    }
                } catch (e  : IOException) {
                    e.printStackTrace()
                    palyFaile()
                } finally {
                    mIsPalying = false
                    //closeQuietly(mFileInputStream)
                    audioTrack.stop()
                    audioTrack.release()
                }
            }

            private fun palyFaile() {
                Log.e("audio","fail")
            }
        }
    }

}